package org.ddd.orderdemo.repository.repository;

import org.ddd.orderdemo.domain.infra.repository.IOrderRepository;
import org.ddd.orderdemo.domain.model.order.Order;
import org.ddd.orderdemo.domain.model.order.OrderItem;
import org.ddd.orderdemo.remote.client.ElasticsearchTemplate;
import org.ddd.orderdemo.remote.client.RedisTemplate;
import org.ddd.orderdemo.repository.convertor.OrderConvertor;
import org.ddd.orderdemo.repository.convertor.OrderItemConvertor;
import org.ddd.orderdemo.repository.po.OrderPo;
import org.ddd.orderdemo.repository.po.es.OrderPoES;
import org.ddd.orderdemo.repository.repository.mapper.OrderItemMapper;
import org.ddd.orderdemo.repository.repository.mapper.OrderMapper;

import java.util.List;
import java.util.Optional;

public class OrderRepository implements IOrderRepository {

//    @Resource
    private OrderMapper orderMapper;

//    @Resource
    private OrderItemMapper orderItemMapper;

//    @Resource
    private RedisTemplate<String, Object> redisTemplate;

//    @Resource
    private ElasticsearchTemplate<OrderPoES, Long> elasticsearchTemplate;

    public Optional<Order> findById(long orderId) {
        return Optional.ofNullable(OrderConvertor.convertToEntityES(elasticsearchTemplate.getById(orderId, OrderPoES.class)));
    }

    /*

    代码解释：
        1. 相对于传统的dao层，资源库的职责更广，在本例中，我们可以在资源库里操作任何的基础存储单元
     （数据库、redis、elastic search等），这样做的好处就如咱们介绍六边形架构的时候说的一样：
     不管存储单元如何更换，都不会影响到核心的业务逻辑代码。
        2.  我们并没有为订单和订单项都单独创建一个资源库，因为我在创建订单的时候肯定也要同步去保存
     订单项的，所以我们只为订单这个聚合分配了一个资源库，这也是DDD推荐的标准做法，这样可以保证逻辑的
     内聚性，防止逻辑分散在领域层。如果我们使用hibernate的cascade（级联）注解的话，这个内聚性会的体现更强。
        3. 模型转换问题：我们可以看到，资源库接收到的都是领域模型，输出的也是领域模型，这样的好处就是，
     我们对业务领域层完全隐藏了技术实现细节，不管你的表结构怎么变，存储组件怎么更换，都不会影响到领域层
     的业务逻辑，因为领域层压根就不关注数据模型(OrderEntity)。从架构层面上来说，我们应用了依赖倒置，领域层
     也根本就不能使用基础设施层的数据模型(OrderEntity)。

     */

    /**
     * 创建订单
     *  @param order
     */
    @Override
    public void createOrder(Order order) {
        //保存订单
        OrderPo orderPo = OrderConvertor.convertToPo(order);
        orderMapper.insert(orderPo);
        order.setOrderId(orderPo.getId());
        //保存订单项
        List<OrderItem> orderItemList = order.getOrderItemList();
        orderItemList.forEach(orderItem -> {
            orderItem.setOrderId(orderPo.getId());
            orderItemMapper.insert(OrderItemConvertor.convertToPo(orderItem));
        });
    }

    @Override
    public Order loadOrder(String orderNo) {
        return null;
    }

    @Override
    public List<Order> getOrders(List<String> orderNos) {
        return List.of();
    }


}
